package com.note.app.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.houbb.sensitive.word.core.SensitiveWordHelper;
import com.note.app.dto.TagDTO;
import com.note.app.mapper.NoteTagMapper;
import com.note.app.mapper.TagMapper;
import com.note.app.service.TagService;
import com.note.common.domain.Tag;
import com.note.common.exception.BusinessException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.time.LocalDateTime;

/**
 * 标签服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TagServiceImpl implements TagService {

    private final TagMapper tagMapper;
    private final NoteTagMapper noteTagMapper;
    
    @Value("${sensitive.word.threshold:10}")
    private int sensitiveWordThreshold;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createTag(Long userId, String name) {
        if (!StringUtils.hasText(name)) {
            throw new BusinessException("标签名称不能为空");
        }
        
        // 敏感词过滤
        String tagName = name.trim();
        if (!tagName.isEmpty()) {
            List<String> nameSensitiveWords = SensitiveWordHelper.findAll(tagName);
            
            if (nameSensitiveWords.size() > sensitiveWordThreshold) {
                throw new BusinessException("标签名称包含过多违规内容，请修改后重试，违规词数量：" + nameSensitiveWords.size());
            }
            
            // 替换敏感词
            if (!nameSensitiveWords.isEmpty()) {
                tagName = SensitiveWordHelper.replace(tagName);
            }
        }

        // 检查是否已存在同名标签
        Tag existingTag = tagMapper.selectByUserIdAndName(userId, tagName);
        if (existingTag != null) {
            return existingTag.getId();
        }

        // 创建新标签
        Tag tag = new Tag();
        tag.setUserId(userId);
        tag.setName(tagName);
        tag.setCreatedAt(LocalDateTime.now());
        tag.setUpdatedAt(LocalDateTime.now());
        tagMapper.insert(tag);

        return tag.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Long> getOrCreateTags(Long userId, List<String> tagNames) {
        if (CollectionUtils.isEmpty(tagNames)) {
            return new ArrayList<>();
        }

        List<Long> tagIds = new ArrayList<>();

        for (String tagName : tagNames) {
            if (StringUtils.hasText(tagName)) {
                tagIds.add(createTag(userId, tagName.trim()));
            }
        }

        return tagIds;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateTag(Long userId, Long tagId, String name) {
        if (!StringUtils.hasText(name)) {
            throw new BusinessException("标签名称不能为空");
        }
        
        // 敏感词过滤
        String tagName = name.trim();
        if (!tagName.isEmpty()) {
            List<String> nameSensitiveWords = SensitiveWordHelper.findAll(tagName);
            
            if (nameSensitiveWords.size() > sensitiveWordThreshold) {
                throw new BusinessException("标签名称包含过多违规内容，请修改后重试，违规词数量：" + nameSensitiveWords.size());
            }
            
            // 替换敏感词
            if (!nameSensitiveWords.isEmpty()) {
                tagName = SensitiveWordHelper.replace(tagName);
            }
        }

        // 检查标签是否存在并属于该用户
        Tag existingTag = tagMapper.selectById(tagId);
        if (existingTag == null || !existingTag.getUserId().equals(userId)) {
            throw new BusinessException("标签不存在或无权限操作");
        }

        // 检查是否已存在同名标签
        Tag nameExistingTag = tagMapper.selectByUserIdAndName(userId, tagName);
        if (nameExistingTag != null && !nameExistingTag.getId().equals(tagId)) {
            throw new BusinessException("已存在同名标签");
        }

        // 更新标签
        Tag tag = new Tag();
        tag.setId(tagId);
        tag.setName(tagName);
        tag.setUpdatedAt(LocalDateTime.now());

        return tagMapper.updateById(tag) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteTag(Long userId, Long tagId) {
        // 检查标签是否存在并属于该用户
        Tag existingTag = tagMapper.selectById(tagId);
        if (existingTag == null || !existingTag.getUserId().equals(userId)) {
            throw new BusinessException("标签不存在或无权限操作");
        }

        // 检查标签是否被笔记引用
        int count = noteTagMapper.countNotesByTagId(tagId);
        if (count > 0) {
            throw new BusinessException("标签已被" + count + "个笔记使用，无法删除");
        }

        // 删除标签
        return tagMapper.deleteById(tagId) > 0;
    }

    @Override
    public Page<TagDTO> getUserTags(Long userId, long current, long size) {
        // 分页查询用户标签
        Page<Tag> page = new Page<>(current, size);
        IPage<Tag> tagPage = tagMapper.selectPageByUserId(page, userId);

        // 转换结果
        Page<TagDTO> result = new Page<>(tagPage.getCurrent(), tagPage.getSize(), tagPage.getTotal());
        List<TagDTO> records = tagPage.getRecords().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());

        result.setRecords(records);
        return result;
    }

    @Override
    public List<TagDTO> getAllUserTags(Long userId) {
        List<Tag> tags = tagMapper.selectAllByUserId(userId);

        return tags.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public List<TagDTO> getTagsByNoteId(Long noteId) {
        List<Tag> tags = tagMapper.selectTagsByNoteId(noteId);

        return tags.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int associateTagsWithNote(Long noteId, List<Long> tagIds) {
        if (CollectionUtils.isEmpty(tagIds)) {
            return 0;
        }

        return noteTagMapper.batchInsert(noteId, tagIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeTagsFromNote(Long noteId) {
        return noteTagMapper.deleteByNoteId(noteId) >= 0;
    }

    /**
     * 将Tag实体转换为TagDTO
     */
    private TagDTO convertToDTO(Tag tag) {
        TagDTO dto = new TagDTO();
        BeanUtils.copyProperties(tag, dto);
        return dto;
    }
}